const VSHADER_SOURCE = `
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  attribute vec4 a_Normal;
  uniform vec3 u_LightColor;
  uniform vec3 u_LightDirection;
  uniform mat4 u_Transform;
  varying vec4 v_Color;
  void main(){
    vec3 normal = normalize(vec3(a_Normal));
    // 光纤方向和法向量点积
    float nDotL = max(dot(u_LightDirection,normal),0.0);
    // 计算漫反射光的颜色
    vec3 diffuse = u_LightColor * vec3(a_Color) * nDotL;
    gl_Position = u_Transform * a_Position;
    // v_Color = vec4(diffuse,a_Color.a);
    v_Color = a_Color;
  }
`
const FSHADER_SOURCE = `
  #ifdef GL_ES
  precision mediump float; 
  #endif
  varying vec4 v_Color;
  void main(){
    gl_FragColor = v_Color;
  }
`

var a_Position, a_Color, u_Transform, a_Normal, u_LightColor, u_LightDirection,
  vshaderBuf, normalBuf, indicesBuf, transformMatrix;
var canvas, gl, ang = 0;

var cameraParam = {
  x: 3,
  y: 3,
  z: 7,
  atX: 0,
  atY: 0,
  atZ: 0,
  upX: 0,
  upY: 1,
  upZ: 0,
  near: 1,
  far: 100,
  fov: 45,
  aspect: 1,
}

var vshaderArr = new Float32Array([
  -1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  -1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, -1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
  1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
  -1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
  -1.0, -1.0, -1.0, 1.0, 1.0, 1.0,
  1.0, -1.0, -1.0, 1.0, 1.0, 1.0,
])

var normalArr = new Float32Array([
  0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
  0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
  1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
  -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
  0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down
  0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0 // v4-v7-v6-v5 back
])

var vshaderIndicesArr = new Uint8Array([
  0, 1, 2, 0, 2, 3, // front,
  0, 4, 5, 0, 3, 4, // up
  3, 2, 7, 3, 7, 4, // right
  0, 5, 6, 0, 6, 1, // left
  1, 6, 7, 1, 7, 2, // bottom
  4, 5, 6, 4, 6, 7 // back
])

function initEnv() {
  canvas = document.getElementById("example");
  transformMatrix = new Matrix4();

  gl = getWebGLContext(canvas);
  gl.enable(gl.DEPTH_TEST);
  gl.clearColor(0, 0, 0, 1);
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.error("initEnv");
  }

  a_Position = gl.getAttribLocation(gl.program, "a_Position");
  a_Color = gl.getAttribLocation(gl.program, "a_Color");
  a_Normal = gl.getAttribLocation(gl.program, "a_Normal");
  u_Transform = gl.getUniformLocation(gl.program, "u_Transform");
  u_LightColor = gl.getUniformLocation(gl.program, "u_LightColor");
  u_LightDirection = gl.getUniformLocation(gl.program, "u_LightDirection");
  if (a_Position < 0 || !a_Color || !u_Transform || !a_Normal ||
    !u_LightColor || !u_LightDirection) {
    console.error("initEnv", a_Position, a_Color, u_Transform);
  }
}

function initVertices() {
  const FSIZE = vshaderArr.BYTES_PER_ELEMENT;

  transformMatrix.setPerspective(cameraParam.fov, cameraParam.aspect, cameraParam.near, cameraParam.far);
  transformMatrix.lookAt(
    cameraParam.x, cameraParam.y, cameraParam.z,
    cameraParam.atX, cameraParam.atY, cameraParam.atZ,
    cameraParam.upX, cameraParam.upY, cameraParam.upZ
  );
  transformMatrix.rotate(ang, 1, 1, 0);
  vshaderBuf = gl.createBuffer();
  indicesBuf = gl.createBuffer();
  normalBuf = gl.createBuffer();

  gl.uniformMatrix4fv(u_Transform, false, transformMatrix.elements);

  gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);
  gl.enableVertexAttribArray(a_Position);

  gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
  gl.enableVertexAttribArray(a_Color);

  gl.bindBuffer(gl.ARRAY_BUFFER, vshaderBuf);
  gl.bufferData(gl.ARRAY_BUFFER, vshaderArr, gl.STATIC_DRAW);

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuf);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, vshaderIndicesArr, gl.STATIC_DRAW);

  gl.bindBuffer(gl.ARRAY_BUFFER, normalBuf);
  gl.bufferData(gl.ARRAY_BUFFER, normalArr, gl.STATIC_DRAW);

  // gl.vertexAttribPointer(a_Normal, 3, gl.FLOAT, false, 0, 0);
  // gl.enableVertexAttribArray(a_Normal);
}

function init() {
  initEnv();
  initVertices();
}

function animate() {
  ang = (ang + 3) % 360;
  initVertices();
  render();
  // requestAnimationFrame(animate);
}

function render() {
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, 0);
  gl.drawElements(gl.TRIANGLES, vshaderIndicesArr.length, gl.UNSIGNED_BYTE, 0);
}

function main() {
  init();
  animate();
}